#! /bin/bash

#  This script is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License version 2 as
#  published by the Free Software Foundation.
#
#  See the COPYING and AUTHORS files for more details.

# Read in library functions
if [ "$(type -t patch_file_name)" != function ]
then
	if ! [ -r $CMDPATH/scripts/patchfns ]
	then
		echo "Cannot read library $CMDPATH/scripts/patchfns" >&2
		exit 1
	fi
	. $CMDPATH/scripts/patchfns
fi

usage()
{
	printf $"Usage: quilt graph [--all] [--reduce] [--lines[=num]] [--edge-labels=files] [patch]\n"

	if [ x$1 = x-h ]
	then
		printf $"
Generate a dot(1) directed graph showing the dependencies between
applied patches. A patch depends on another patch if both touch the same
file or, with the --lines option, if their modifications overlap. Unless
otherwise specified, the graph includes all patches that the topmost
patch depends on.
When a patch name is specified, instead of the topmost patch, create a
graph for the specified patch. The graph will include all other patches
that this patch depends on, as well as all patches that depend on this
patch.

--all	Generate a graph including all applied patches and their
	dependencies. (Unapplied patches are not included.)

--reduce
	Eliminate transitive edges from the graph.

--lines[=num]
	Compute dependencies by looking at the lines the patches modify.
	Unless a different num is specified, two lines of context are
	included.

--edge-labels=files
	Label graph edges with the file names that the adjacent patches
	modify.

-T ps	Directly produce a PostScript output file.
"
		exit 0
	else
		exit 1
	fi
}

options=`getopt -o T:h --long all,reduce,lines::,edge-labels: -- "$@"`

if [ $? -ne 0 ]
then
	usage
fi

eval set -- "$options"

while true
do
	case "$1" in
	-T)	if [ "$2" != ps ]; then
			usage
		fi
		opt_format=ps
		shift 2 ;;

	--all)
		opt_all=1
		shift ;;

	--reduce)
		opt_reduce=1
		shift ;;

	--lines)
		opt_lines=${2:-2}
		shift 2 ;;
		
	--edge-labels)
		if [ "$2" != files ]
		then
			usage
		fi
		opt_edge_labels=$2
		shift 2 ;;

	-h)
		usage -h ;;

	--)
		shift
		break ;;
	esac
done

if [ $# -gt 1 -o \( $# -ne 0 -a -n "$opt_all" \) ]
then
	usage
fi

if [ $# -eq 1 ]
then
	if ! patch=$(find_patch $1)
	then
		printf $"Patch %s is not in series\n" "$1" >&2
		exit 1
	fi
	if ! is_applied $patch
	then
		printf $"Patch %s is not applied\n" "$(print_patch $patch)" >&2
		exit 1
	fi
fi

if [ -z "$opt_all" -a -z "$patch" ]
then
	patch=$(top_patch)
	if [ -z "$patch" ]
	then
		printf $"No patches applied\n" >&2
		exit 1
	fi
fi

options=
[ -n "$patch" ] && options="--select-patch $patch"
[ -n "$opt_reduce" ] && options="$options --reduce"
[ "$opt_edge_labels" = files ] && options="$options --edge-files"
[ -n "$opt_lines" ] && options="$options --lines=$opt_lines"

pipe=
[ -n "$opt_format" ] && pipe="| dot -T$opt_format"

applied_patches \
| eval $CMDPATH/scripts/dependency-graph $options - $pipe
### Local Variables:
### mode: shell-script
### End:
# vim:filetype=sh
